home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / boot / czesc_2 / toolmanager / source / library / readiff.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  16KB  |  570 lines

  1. /*
  2.  * readiff.c  V2.1
  3.  *
  4.  * read IFF ILBM/ANIM files
  5.  *
  6.  * (c) 1990-1993 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* Bitmap header (BMHD) structure */
  12. struct BitMapHeader {
  13.                      UWORD w,h;                   /* Width, height in pixels */
  14.                      WORD  x,y;
  15.                      UBYTE nplanes;               /* Number of planes */
  16.                      UBYTE Masking;               /* Masking */
  17.                      UBYTE Compression;           /* Compression algorithm */
  18.                      UBYTE pad1;
  19.                      UWORD TransparentColor;
  20.                      UBYTE XAspect,YAspect;
  21.                      WORD  PageWidth, PageHeight;
  22.                     };
  23. #define MSK_HASMASK   1
  24. #define COMP_NO       0
  25. #define COMP_BYTERUN1 1
  26. #define BPR(w)        ((((w)+15)>>4)<<1) /* Bytes per row formula */
  27.  
  28. /* Animation header (ANHD) structure */
  29. struct AnimHeader {
  30.                    UBYTE operation;  /* We only accept code 5 */
  31.                    UBYTE mask;
  32.                    UWORD w,h;
  33.                    WORD  x,y;
  34.                    ULONG abstime;
  35.                    ULONG reltime;    /* timing in jiffies (1/60 seconds) */
  36.                    UBYTE interleave; /* We only accept 0(=2), 1 & 2 */
  37.                    UBYTE pad0;
  38.                    ULONG bits;
  39.                   };
  40.  
  41. /* IFF ID's */
  42. #define ID_ILBM MAKE_ID('I','L','B','M')
  43. #define ID_BMHD MAKE_ID('B','M','H','D')
  44. #define ID_BODY MAKE_ID('B','O','D','Y')
  45. #define ID_ANIM MAKE_ID('A','N','I','M')
  46. #define ID_ANHD MAKE_ID('A','N','H','D')
  47. #define ID_DLTA MAKE_ID('D','L','T','A')
  48.  
  49. /* Read IFF ILBM BODY Chunk */
  50. static BOOL ReadBODYChunk(struct IFFHandle *iff, struct BitMapHeader *bmhd,
  51.                           UBYTE *dest, ULONG bpr, ULONG planeoff)
  52. {
  53.  UBYTE *src;
  54.  ULONG size=CurrentChunk(iff)->cn_Size;
  55.  BOOL rc=FALSE;
  56.  
  57.  DEBUG_PRINTF("IFF: Read BODY chunk\n");
  58.  
  59.  /* Get memory for BODY chunk contents */
  60.  if (src=AllocMem(size,MEMF_PUBLIC)) {
  61.   /* Read in the complete BODY chunk */
  62.   if (ReadChunkBytes(iff,src,size)==size) {
  63.    register UBYTE *sp=src;
  64.    ULONG row;
  65.    BOOL ncomp=bmhd->Compression==COMP_NO;
  66.    BOOL mask=bmhd->Masking==MSK_HASMASK;
  67.  
  68.    /* Read data row by row */
  69.    for (row=0; row<bmhd->h; row++) {
  70.     ULONG pl;
  71.  
  72.     /* Read data plane by plane */
  73.     for (pl=0; pl<bmhd->nplanes; pl++) {
  74.      UBYTE *dp;
  75.  
  76.      /* Calculate destination pointer */
  77.      dp=dest+pl*planeoff+row*bpr;
  78.  
  79.      /* Compressed? */
  80.      if (ncomp) {
  81.       /* No compression */
  82.       UBYTE k;
  83.  
  84.       for (k=bpr; k--;) *dp++=*sp++; /* Copy all bytes */
  85.      } else {
  86.       /* Byte Run compression */
  87.       ULONG rem=bpr;
  88.  
  89.       /* Row not completed */
  90.       while (rem) {
  91.        BYTE k=*sp++; /* Read compression code */
  92.  
  93.        if (k>=0) {
  94.         /* Literal copy */
  95.         if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
  96.  
  97.         while (k--) *dp++=*sp++;        /* Copy the following k+1 bytes */
  98.        } else if (k!=-128) {            /* Code -128 == No Operation */
  99.         /* Byte run encoded */
  100.         UBYTE byte;
  101.  
  102.         k=-k;
  103.         if ((rem-=++k)<0) goto comperr; /* Error in de-compression? */
  104.  
  105.         byte=*sp++;                     /* Get byte */
  106.         while (k--) *dp++=byte;         /* Copy this byte -k+1 times */
  107.        }
  108.       }
  109.      }
  110.     }
  111.  
  112.     /* Skip mask plane */
  113.     if (mask)
  114.      /* Compressed? */
  115.      if (ncomp)
  116.       /* No compression */
  117.       sp+=bpr;
  118.      else {
  119.       /* Byte Run compression */
  120.       ULONG rem=bpr;
  121.  
  122.       /* Row not completed */
  123.       while (rem) {
  124.        BYTE k=*sp++; /* Read compression code */
  125.  
  126.        if (k>=0) {
  127.         /* Literal copy */
  128.         if ((rem-=++k)<0) goto comperr;  /* Error in de-compression? */
  129.         sp+=k;                           /* Skip the following k+1 bytes */
  130.        } else if (k!=-128) {             /* Code -128 == No Operation */
  131.         /* Byte run encoded */
  132.         k=-k;
  133.         if ((rem-=++k)<0) goto comperr;  /* Error in de-compression? */
  134.         sp++;                            /* Skip this byte */
  135.        }
  136.       }
  137.      }
  138.    }
  139.  
  140.    /* All OK */
  141.    rc=TRUE;
  142. comperr: /* Got a compression error */
  143.   }
  144.   FreeMem(src,size);
  145.  }
  146.  return(rc);
  147. }
  148.  
  149. /* Read IFF ILBM Chunk */
  150. static struct TMImageData *ReadILBMChunk(struct IFFHandle *iff)
  151. {
  152.  struct TMImageData *tmid;
  153.  
  154.  DEBUG_PRINTF("IFF: Read ILBM chunk\n");
  155.  
  156.  /* Allocate memory for main data structure */
  157.  if (tmid=AllocMem(sizeof(struct TMImageData),MEMF_PUBLIC|MEMF_CLEAR)) {
  158.  
  159.       /* BMHD: FORM ILBM property chunk */
  160.   if (!PropChunk(iff,ID_ILBM,ID_BMHD) &&
  161.  
  162.       /* BODY: FORM ILBM image data chunk */
  163.       !StopChunk(iff,ID_ILBM,ID_BODY) &&
  164.  
  165.       /* FORM: begin of next context */
  166.       !StopOnExit(iff,ID_ILBM,ID_FORM) &&
  167.  
  168.       /* Chunk types set, start parsing */
  169.       !ParseIFF(iff,IFFPARSE_SCAN)) {
  170.  
  171.    struct StoredProperty *sp;
  172.  
  173.    /* BMHD chunk found? */
  174.    if (sp=FindProp(iff,ID_ILBM,ID_BMHD)) {
  175.     struct BitMapHeader *bmhd=(struct BitMapHeader *) sp->sp_Data;
  176.  
  177.     /* Check compression type */
  178.     if ((bmhd->Compression==COMP_NO) || (bmhd->Compression==COMP_BYTERUN1)) {
  179.      struct TMImageNode *tmin;
  180.  
  181.      /* Alloc memory for TMImageNode */
  182.      if (tmin=AllocMem(sizeof(struct TMImageNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  183.       ULONG bpr,planeoff,size;
  184.  
  185.       /* Calculate sizes */
  186.       bpr=BPR(bmhd->w);            /* Bytes per row */
  187.       planeoff=bpr*bmhd->h;        /* Bytes per bitplane */
  188.       size=planeoff*bmhd->nplanes; /* Bytes for image data */
  189.  
  190.       /* Alloc memory for image data */
  191.       if (tmin->tmin_Data=AllocMem(size,MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR)) {
  192.        /* Read BODY Chunk */
  193.        if (ReadBODYChunk(iff,bmhd,(UBYTE *) tmin->tmin_Data,bpr,planeoff)) {
  194.         /* Retrieve BMHD chunk values */
  195.         tmid->tmid_Normal.Width=bmhd->w;
  196.         tmid->tmid_Normal.Height=bmhd->h;
  197.         tmid->tmid_Normal.Depth=bmhd->nplanes;
  198.         tmid->tmid_Normal.PlanePick=(1L<<bmhd->nplanes)-1;
  199.  
  200.         /* Copy values to second Image struct */
  201.         tmid->tmid_Selected=tmid->tmid_Normal;
  202.  
  203.         /* Init rest of structure */
  204.         tmid->tmid_Normal.ImageData=tmin->tmin_Data;
  205.         tmid->tmid_Data=tmin;
  206.  
  207.         /* All OK. */
  208.         return(tmid);
  209.        }
  210.        FreeMem(tmin->tmin_Data,size);
  211.       }
  212.       FreeMem(tmin,sizeof(struct TMImageNode));
  213.      }
  214.     }
  215.    }
  216.   }
  217.  
  218.   FreeMem(tmid,sizeof(struct TMImageData));
  219.  }
  220.  return(NULL);
  221. }
  222.  
  223. /* Read one ANIM frame */
  224. static BOOL ReadFrame(struct IFFHandle *iff, struct TMImageData *tmid,
  225.                       struct TMImageNode **tminptr, ULONG size, BOOL *int2)
  226. {
  227.  struct StoredProperty *sp;
  228.  
  229.  DEBUG_PRINTF("IFF: Read ANIM Frame\n");
  230.  
  231.  /* Get ANHD chunk */
  232.  if (sp=FindProp(iff,ID_ILBM,ID_ANHD)) {
  233.   struct AnimHeader *ah=(struct AnimHeader *) sp->sp_Data;
  234.  
  235.   DEBUG_PRINTF("IFF: ANIM Opcode %ld\n",ah->operation);
  236.  
  237.   /* Check anim type (Only type 5 supported) and interleave */
  238.   if ((ah->operation==5) && (ah->interleave<=2)) {
  239.    UBYTE *chunkbuf;
  240.    ULONG chunksize=CurrentChunk(iff)->cn_Size;
  241.  
  242.    DEBUG_PRINTF("IFF: DLTA chunk length %ld\n",chunksize);
  243.  
  244.    /* Alloc buffer for chunk data */
  245.    if (chunkbuf=AllocMem(chunksize,MEMF_PUBLIC)) {
  246.     /* Read chunk data */
  247.     if (ReadChunkBytes(iff,chunkbuf,chunksize)==chunksize) {
  248.      struct TMImageNode *tmin;
  249.  
  250.      DEBUG_PRINTF("IFF: DLTA chunk read\n");
  251.  
  252.      /* Alloc image node */
  253.      if (tmin=AllocMem(sizeof(struct TMImageNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  254.       /* Alloc memory for image data */
  255.       if (tmin->tmin_Data=AllocMem(size,MEMF_PUBLIC|MEMF_CHIP)) {
  256.        ULONG bpr=BPR(tmid->tmid_Normal.Width);
  257.        ULONG rows=tmid->tmid_Normal.Height;
  258.        ULONG planeoff=bpr*rows;
  259.        ULONG pl,planes=tmid->tmid_Normal.Depth;
  260.  
  261.        /* Interleave == 1?? */
  262.        if (ah->interleave==1) {
  263.         /* Yes. ANIM with 1 image interleave (DP ANIM brush). First image? */
  264.         if (!(*tminptr))
  265.          /* Yes. Set pointer. */
  266.          *tminptr=tmid->tmid_Data;
  267.  
  268.         /* Copy old frame to new buffer */
  269.         CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
  270.  
  271.         /* Append new image node to list, move pointer */
  272.         (*tminptr)->tmin_Next=tmin;
  273.         *tminptr=tmin;
  274.        }
  275.        else {
  276.         /* No. ANIM with 2 images interleave. First image? */
  277.  
  278.         if (!(*tminptr)) {
  279.          /* Yes. Set pointer */
  280.          *tminptr=tmid->tmid_Data;
  281.  
  282.          /* Copy old frame to new buffer */
  283.          CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
  284.         } else {
  285.          /* No. Copy old frame to new buffer */
  286.          CopyMem((*tminptr)->tmin_Data,tmin->tmin_Data,size);
  287.  
  288.          /* Move pointer */
  289.          *tminptr=(*tminptr)->tmin_Next;
  290.  
  291.         }
  292.  
  293.         /* Append new image node to list */
  294.         (*tminptr)->tmin_Next=tmin;
  295.  
  296.         /* Interleave==2 */
  297.         *int2=TRUE;
  298.        }
  299.  
  300.        DEBUG_PRINTF("chunkbuf 0x%08lx",chunkbuf);
  301.        DEBUG_PRINTF(" imagedata 0x%08lx\n",tmin->tmin_Data);
  302.  
  303.        /* XOR or STORE method? */
  304.        if (ah->bits & 0x2)
  305.         /* Apply DLTA data to frame for each plane with XOR method */
  306.         for (pl=0; pl<planes; pl++) {
  307.          ULONG off=*((ULONG *) chunkbuf+pl);
  308.  
  309.          /* Any data for this plane? */
  310.          if (off) {
  311.           ULONG col;
  312.           register UBYTE *sp=chunkbuf+off;
  313.           UBYTE *plane=(UBYTE *) tmin->tmin_Data+pl*planeoff;
  314.  
  315.           /* For each byte column in this plane */
  316.           for (col=0; col<bpr; col++) {
  317.            UBYTE *dp=plane+col;
  318.            LONG opcount=*sp++;
  319.  
  320.            while (opcount-->0) {
  321.             UBYTE code=*sp++; /* Get code */
  322.  
  323.             if (code==0) {
  324.              /* Same bytes */
  325.              UBYTE count=*sp++;
  326.              UBYTE byte=*sp++;
  327.  
  328.              /* Copy byte count times */
  329.              while (count--) {
  330.               *dp^=byte;
  331.               dp+=bpr; /* next ROW! */
  332.              }
  333.             } else if (code & 0x80) {
  334.              /* Literal copy */
  335.              UBYTE count=code&0x7f; /* Strip high bit */
  336.  
  337.              /* Copy data */
  338.              while (count--) {
  339.               *dp^=*sp++;
  340.               dp+=bpr; /* next ROW! */
  341.              }
  342.             } else
  343.              /* Move destination pointer code rows */
  344.              dp+=code*bpr;
  345.            }
  346.           }
  347.          }
  348.         }
  349.        else
  350.         /* Apply DLTA data to frame for each plane with STORE method */
  351.         for (pl=0; pl<planes; pl++) {
  352.          ULONG off=*((ULONG *) chunkbuf+pl);
  353.  
  354.          /* Any data for this plane? */
  355.          if (off) {
  356.           ULONG col;
  357.           register UBYTE *sp=chunkbuf+*((ULONG *) chunkbuf+pl);
  358.           UBYTE *plane=(UBYTE *) tmin->tmin_Data+pl*planeoff;
  359.  
  360.           /* For each byte column in this plane */
  361.           for (col=0; col<bpr; col++) {
  362.            UBYTE *dp=plane+col;
  363.            LONG opcount=*sp++;
  364.  
  365.            while (opcount-->0) {
  366.             UBYTE code=*sp++; /* Get code */
  367.  
  368.             if (code==0) {
  369.              /* Same bytes */
  370.              UBYTE count=*sp++;
  371.              UBYTE byte=*sp++;
  372.  
  373.              /* Copy byte count times */
  374.              while (count--) {
  375.               *dp=byte;
  376.               dp+=bpr; /* next ROW! */
  377.              }
  378.             } else if (code & 0x80) {
  379.              /* Literal copy */
  380.              UBYTE count=code&0x7f; /* Strip high bit */
  381.  
  382.              /* Copy data */
  383.              while (count--) {
  384.               *dp=*sp++;
  385.               dp+=bpr; /* next ROW! */
  386.              }
  387.             } else
  388.              /* Move destination pointer code rows */
  389.              dp+=code*bpr;
  390.            }
  391.           }
  392.          }
  393.         }
  394.  
  395.        /* All OK! free chunk buffer */
  396.        FreeMem(chunkbuf,chunksize);
  397.        return(TRUE);
  398.       }
  399.       FreeMem(tmin,sizeof(struct TMImageNode));
  400.      }
  401.     }
  402.     FreeMem(chunkbuf,chunksize);
  403.    }
  404.   }
  405.  }
  406.  return(FALSE);
  407. }
  408.  
  409. /* Read IFF ANIM Chunk */
  410. static struct TMImageData *ReadANIMChunk(struct IFFHandle *iff)
  411. {
  412.  struct TMImageData *tmid=NULL;
  413.  
  414.  DEBUG_PRINTF("IFF: Read ANIM chunk\n");
  415.  
  416.  /* Go to first ILBM chunk */
  417.  if (!ParseIFF(iff,IFFPARSE_STEP)) {
  418.   struct ContextNode *cn;
  419.  
  420.   DEBUG_PRINTF("IFF: Skipped FORM ANIM chunk\n");
  421.  
  422.   /* Get current IFF chunk context, check chunk ID & type, read ILBM chunk */
  423.   if ((cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM) &&
  424.       (cn->cn_Type==ID_ILBM) && (tmid=ReadILBMChunk(iff))) {
  425.  
  426.    ULONG size=BPR(tmid->tmid_Normal.Width) * tmid->tmid_Normal.Height *
  427.               tmid->tmid_Normal.Depth;
  428.    struct TMImageNode *tmin=NULL;
  429.    struct TMImageNode *lasttmin=tmid->tmid_Data;
  430.    struct TMImageNode *last2tmin=NULL;
  431.    struct TMImageNode *last3tmin=NULL;
  432.    BOOL int2=FALSE;
  433.  
  434.    /* Skip rest of current ILBM FORM */
  435.    while (ParseIFF(iff,IFFPARSE_SCAN)==IFFERR_EOC)
  436.         /* Step to next FORM chunk */
  437.     if (!ParseIFF(iff,IFFPARSE_STEP) &&
  438.  
  439.         /* Check type of current chunk */
  440.         (cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM) &&
  441.         (cn->cn_Type==ID_ILBM) &&
  442.  
  443.         /* ANHD: FORM ANIM property chunk */
  444.         !PropChunk(iff,ID_ILBM,ID_ANHD) &&
  445.  
  446.         /* DLTA: FORM ANIM data chunk */
  447.         !StopChunk(iff,ID_ILBM,ID_DLTA) &&
  448.  
  449.         /* FORM: begin of next frame */
  450.         !StopOnExit(iff,ID_ILBM,ID_FORM) &&
  451.  
  452.         /* Start parsing */
  453.         !ParseIFF(iff,IFFPARSE_SCAN) &&
  454.  
  455.         /* Read frame */
  456.         ReadFrame(iff,tmid,&tmin,size,&int2)) {
  457.      /* Move pointer chain */
  458.      last3tmin=last2tmin;
  459.      last2tmin=lasttmin;
  460.      lasttmin=lasttmin->tmin_Next;
  461.     }
  462.     else break;
  463.  
  464.    /* ANIM chunk read */
  465.    /* Delete last (int2==FALSE) or last two (int2==TRUE) frames. */
  466.    /* These frames are unnecessary, because they are duplicates. */
  467.    /* Got at least three nodes? */
  468.    if (last3tmin) {
  469.     /* Yes. Interleave==2 and at least four nodes? */
  470.     if (int2 && (last3tmin!=tmid->tmid_Data)) {
  471.       /* Yes. Delete second to last node */
  472.       FreeMem(last2tmin->tmin_Data,size);
  473.       FreeMem(last2tmin,sizeof(struct TMImageNode));
  474.  
  475.       /* Cut list off after third to last node */
  476.       last3tmin->tmin_Next=NULL;
  477.     } else
  478.      /* No. Cut list off after second to last node */
  479.      last2tmin->tmin_Next=NULL;
  480.  
  481.     /* Delete last node */
  482.     FreeMem(lasttmin->tmin_Data,size);
  483.     FreeMem(lasttmin,sizeof(struct TMImageNode));
  484.    }
  485.  
  486.    /* Init rest of structure */
  487.    if (tmin=tmid->tmid_Data->tmin_Next)
  488.     tmid->tmid_Selected.ImageData=tmin->tmin_Data;
  489.   }
  490.  }
  491.  return(tmid);
  492. }
  493.  
  494. /* Read IFF file */
  495. struct TMImageData *ReadIFFData(char *name)
  496. {
  497.  struct TMImageData *tmid=NULL;
  498.  
  499.  /* Open IFF parsing library */
  500.  if (IFFParseBase=OpenLibrary("iffparse.library",0)) {
  501.   struct IFFHandle *iff;
  502.  
  503.   DEBUG_PRINTF("IFF Library opened.\n");
  504.  
  505.   /* Alloc IFF handle */
  506.   if (iff=AllocIFF()) {
  507.  
  508.    DEBUG_PRINTF("IFF Handle (0x%08lx)\n",iff);
  509.  
  510.    /* Open IFF file */
  511.    if (iff->iff_Stream=Open(name,MODE_OLDFILE)) {
  512.     /* Init IFF handle */
  513.     InitIFFasDOS(iff);
  514.  
  515.     DEBUG_PRINTF("IFF Stream (0x%08lx)\n",iff->iff_Stream);
  516.  
  517.     /* Open IFF handle */
  518.     if (!OpenIFF(iff,IFFF_READ)) {
  519.  
  520.      DEBUG_PRINTF("IFF Opened\n");
  521.  
  522.      /* Start IFF parsing */
  523.      if (!ParseIFF(iff,IFFPARSE_STEP)) {
  524.       struct ContextNode *cn;
  525.  
  526.       /* Get current IFF chunk context and check for FORM chunk ID */
  527.       if ((cn=CurrentChunk(iff)) && (cn->cn_ID==ID_FORM))
  528.        /* Yes. Check for FORM type */
  529.        switch (cn->cn_Type) {
  530.         case ID_ILBM:tmid=ReadILBMChunk(iff); /* FORM ILBM file */
  531.                      break;
  532.         case ID_ANIM:tmid=ReadANIMChunk(iff); /* FORM ANIM file */
  533.                      break;
  534.        }
  535.      }
  536.      CloseIFF(iff);
  537.     }
  538.     Close(iff->iff_Stream);
  539.    }
  540.    FreeIFF(iff);
  541.   }
  542.   CloseLibrary(IFFParseBase);
  543.  }
  544.  return(tmid);
  545. }
  546.  
  547. /* Free IFF Data */
  548. void FreeIFFData(struct TMImageData *tmid)
  549. {
  550.  struct TMImageNode *tmin1,*tmin2=tmid->tmid_Data;
  551.  ULONG size=BPR(tmid->tmid_Normal.Width) * tmid->tmid_Normal.Height *
  552.             tmid->tmid_Normal.Depth;
  553.  
  554.  /* Free all image datas and nodes */
  555.  while (tmin1=tmin2) {
  556.   /* Get pointer to next node */
  557.   tmin2=tmin1->tmin_Next;
  558.  
  559.   /* Free Image Data */
  560.   FreeMem(tmin1->tmin_Data,size);
  561.  
  562.   /* Free Node */
  563.   FreeMem(tmin1,sizeof(struct TMImageNode));
  564.  }
  565.  
  566.  /* Free main structure */
  567.  FreeMem(tmid,sizeof(struct TMImageData));
  568. }
  569.  
  570.